#!/usr/bin/env python3
"""
简单监控面板 - 第1.5阶段核心组件
负责实时监控爬取进度，显示账号状态，提供可视化面板
"""

import logging
import time
import json
from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta
from pathlib import Path

logger = logging.getLogger(__name__)

class SimpleMonitor:
    """简单监控面板 - 第1.5阶段"""
    
    def __init__(self, account_manager=None, scheduler=None):
        """初始化监控面板"""
        logger.info("[MONITOR] 初始化监控面板...")
        
        self.account_manager = account_manager
        self.scheduler = scheduler
        
        # 会话统计
        self.session_stats = {
            'session_id': None,
            'start_time': None,
            'current_account': None,
            'total_crawled': 0,
            'success_count': 0,
            'error_count': 0,
            'success_rate': 0.0,
            'errors': [],
            'last_update': time.time()
        }
        
        # 历史统计
        self.history_stats = {
            'daily_total': 0,
            'weekly_total': 0,
            'sessions_today': 0,
            'best_session': 0,
            'avg_session': 0
        }
        
        # 告警配置
        self.alert_config = {
            'success_rate_threshold': 0.8,
            'error_rate_threshold': 0.2,
            'session_timeout': 7200,  # 2小时
            'max_consecutive_errors': 3
        }
        
        logger.info("[MONITOR] ✅ 监控面板初始化完成")
    
    def start_session(self, account_id: str, session_config: Dict = None):
        """开始监控会话"""
        session_id = f"session_{int(time.time())}"
        
        self.session_stats.update({
            'session_id': session_id,
            'start_time': time.time(),
            'current_account': account_id,
            'total_crawled': 0,
            'success_count': 0,
            'error_count': 0,
            'success_rate': 0.0,
            'errors': [],
            'last_update': time.time(),
            'config': session_config or {}
        })
        
        self.history_stats['sessions_today'] += 1
        
        logger.info(f"[MONITOR] 🚀 开始监控会话: {session_id} (账号: {account_id})")
        
        # 如果有调度器，通知开始会话
        if self.scheduler:
            self.scheduler.start_session()
    
    def update_progress(self, data_count: int, success: bool, error_info: str = None):
        """更新进度"""
        if success:
            self.session_stats['total_crawled'] += data_count
            self.session_stats['success_count'] += 1
            self.history_stats['daily_total'] += data_count
            
            # 更新调度器进度
            if self.scheduler:
                self.scheduler.update_session_progress(data_count)
                
        else:
            self.session_stats['error_count'] += 1
            
            # 记录错误信息
            error_record = {
                'timestamp': time.time(),
                'account': self.session_stats['current_account'],
                'error_info': error_info or 'Unknown error',
                'session_progress': self.session_stats['total_crawled']
            }
            self.session_stats['errors'].append(error_record)
            
            # 保持错误记录在合理范围内
            if len(self.session_stats['errors']) > 50:
                self.session_stats['errors'] = self.session_stats['errors'][-25:]
        
        # 计算成功率
        total_attempts = self.session_stats['success_count'] + self.session_stats['error_count']
        if total_attempts > 0:
            self.session_stats['success_rate'] = self.session_stats['success_count'] / total_attempts
        
        self.session_stats['last_update'] = time.time()
        
        # 检查告警条件
        self.check_alerts()
    
    def switch_account(self, new_account_id: str, reason: str = "Manual switch"):
        """切换账号"""
        old_account = self.session_stats['current_account']
        self.session_stats['current_account'] = new_account_id
        
        logger.info(f"[MONITOR] 🔄 账号切换: {old_account} → {new_account_id} (原因: {reason})")
        
        # 记录切换事件
        switch_record = {
            'timestamp': time.time(),
            'from_account': old_account,
            'to_account': new_account_id,
            'reason': reason,
            'session_progress': self.session_stats['total_crawled']
        }
        
        if 'account_switches' not in self.session_stats:
            self.session_stats['account_switches'] = []
        self.session_stats['account_switches'].append(switch_record)
    
    def end_session(self, reason: str = "Normal completion"):
        """结束会话"""
        if self.session_stats['start_time']:
            session_duration = time.time() - self.session_stats['start_time']
            
            # 更新历史统计
            if self.session_stats['total_crawled'] > self.history_stats['best_session']:
                self.history_stats['best_session'] = self.session_stats['total_crawled']
            
            # 计算平均值
            if self.history_stats['sessions_today'] > 0:
                self.history_stats['avg_session'] = self.history_stats['daily_total'] / self.history_stats['sessions_today']
            
            logger.info(f"[MONITOR] 🏁 会话结束: {self.session_stats['session_id']}")
            logger.info(f"[MONITOR] 会话时长: {session_duration/60:.1f}分钟")
            logger.info(f"[MONITOR] 爬取数据: {self.session_stats['total_crawled']}条")
            logger.info(f"[MONITOR] 成功率: {self.session_stats['success_rate']:.1%}")
            logger.info(f"[MONITOR] 结束原因: {reason}")
            
            # 重置会话统计
            self.session_stats.update({
                'session_id': None,
                'start_time': None,
                'current_account': None,
                'total_crawled': 0,
                'success_count': 0,
                'error_count': 0,
                'success_rate': 0.0,
                'errors': []
            })
    
    def check_alerts(self):
        """检查告警条件"""
        alerts = []
        
        # 检查成功率
        if (self.session_stats['success_rate'] < self.alert_config['success_rate_threshold'] and 
            self.session_stats['success_count'] + self.session_stats['error_count'] >= 5):
            alerts.append({
                'type': 'LOW_SUCCESS_RATE',
                'message': f"成功率过低: {self.session_stats['success_rate']:.1%}",
                'severity': 'warning'
            })
        
        # 检查连续错误
        recent_errors = [e for e in self.session_stats['errors'] 
                        if time.time() - e['timestamp'] < 1800]  # 30分钟内
        if len(recent_errors) >= self.alert_config['max_consecutive_errors']:
            alerts.append({
                'type': 'CONSECUTIVE_ERRORS',
                'message': f"30分钟内连续错误 {len(recent_errors)} 次",
                'severity': 'error'
            })
        
        # 检查会话超时
        if (self.session_stats['start_time'] and 
            time.time() - self.session_stats['start_time'] > self.alert_config['session_timeout']):
            alerts.append({
                'type': 'SESSION_TIMEOUT',
                'message': f"会话超时: {(time.time() - self.session_stats['start_time'])/3600:.1f}小时",
                'severity': 'warning'
            })
        
        # 输出告警
        for alert in alerts:
            if alert['severity'] == 'error':
                logger.error(f"[MONITOR] 🚨 {alert['type']}: {alert['message']}")
            else:
                logger.warning(f"[MONITOR] ⚠️ {alert['type']}: {alert['message']}")
    
    def get_dashboard_data(self) -> Dict:
        """获取监控面板数据"""
        # 获取账号池状态
        account_status = {}
        if self.account_manager:
            account_status = self.account_manager.get_pool_status()
        
        # 获取调度器状态
        scheduler_status = {}
        if self.scheduler:
            scheduler_status = self.scheduler.get_scheduler_status()
        
        # 计算会话时长
        session_duration = 0
        if self.session_stats['start_time']:
            session_duration = time.time() - self.session_stats['start_time']
        
        return {
            'session_info': {
                'session_id': self.session_stats['session_id'],
                'current_account': self.session_stats['current_account'],
                'session_duration': session_duration,
                'data_crawled': self.session_stats['total_crawled'],
                'success_rate': f"{self.session_stats['success_rate']:.1%}",
                'success_count': self.session_stats['success_count'],
                'error_count': self.session_stats['error_count'],
                'last_update': datetime.fromtimestamp(self.session_stats['last_update']).strftime('%H:%M:%S')
            },
            'account_pools': account_status,
            'scheduler_status': scheduler_status,
            'daily_progress': {
                'target': scheduler_status.get('daily_progress', {}).get('total_target', 2000),
                'completed': self.history_stats['daily_total'],
                'remaining': max(0, scheduler_status.get('daily_progress', {}).get('total_target', 2000) - self.history_stats['daily_total']),
                'sessions_today': self.history_stats['sessions_today'],
                'best_session': self.history_stats['best_session'],
                'avg_session': self.history_stats['avg_session']
            },
            'recent_errors': self.session_stats['errors'][-5:] if self.session_stats['errors'] else [],
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def print_dashboard(self):
        """打印监控面板"""
        data = self.get_dashboard_data()
        
        print("\n" + "="*80)
        print("🖥️  第1.5阶段智能爬虫监控面板")
        print("="*80)
        
        # 会话信息
        session = data['session_info']
        if session['session_id']:
            print(f"📊 当前会话: {session['session_id']}")
            print(f"   账号: {session['current_account']}")
            print(f"   时长: {session['session_duration']/60:.1f}分钟")
            print(f"   已爬取: {session['data_crawled']}条")
            print(f"   成功率: {session['success_rate']} ({session['success_count']}成功/{session['error_count']}失败)")
            print(f"   最后更新: {session['last_update']}")
        else:
            print("📊 当前会话: 无活动会话")
        
        # 账号池状态
        pools = data['account_pools']
        if pools:
            print(f"\n🏢 公司账号池: {pools['company_pool']['available']}/{pools['company_pool']['total']} 可用")
            print(f"   使用中: {pools['company_pool']['in_use']}, 冷却中: {pools['company_pool']['cooling']}")
            print(f"🏠 家庭账号池: {pools['home_pool']['available']}/{pools['home_pool']['total']} 可用")
            print(f"   使用中: {pools['home_pool']['in_use']}, 冷却中: {pools['home_pool']['cooling']}")
        
        # 调度器状态
        scheduler = data['scheduler_status']
        if scheduler:
            print(f"\n🌐 网络环境: {scheduler['current_network']} ({scheduler['current_time_slot']})")
            print(f"📋 当前计划: {scheduler['current_plan']['time_slot']} - 目标{scheduler['current_plan']['target_data']}条")
            print(f"⏰ 适合爬取: {'是' if scheduler['should_crawl'] else '否'}")
            if scheduler['next_optimal_time']:
                print(f"   下次最优时间: {scheduler['next_optimal_time']}")
        
        # 每日进度
        daily = data['daily_progress']
        progress_percentage = daily['completed'] / daily['target'] if daily['target'] > 0 else 0
        progress_bar = "█" * int(progress_percentage * 30)
        print(f"\n📈 今日进度: {daily['completed']}/{daily['target']} [{progress_bar:<30}] {progress_percentage:.1%}")
        print(f"   会话数: {daily['sessions_today']}, 最佳: {daily['best_session']}条, 平均: {daily['avg_session']:.0f}条")
        
        # 最近错误
        recent_errors = data['recent_errors']
        if recent_errors:
            print(f"\n⚠️ 最近错误 (最新{len(recent_errors)}条):")
            for error in recent_errors[-3:]:  # 只显示最新3条
                error_time = datetime.fromtimestamp(error['timestamp']).strftime('%H:%M:%S')
                print(f"   {error_time} - {error['account']}: {error['error_info']}")
        
        print("="*80)
        print(f"📅 更新时间: {data['timestamp']}")
        print("="*80)
    
    def print_simple_status(self):
        """打印简化状态信息"""
        data = self.get_dashboard_data()
        session = data['session_info']
        daily = data['daily_progress']
        
        if session['session_id']:
            print(f"[状态] 账号:{session['current_account']} | "
                  f"已爬取:{session['data_crawled']}条 | "
                  f"成功率:{session['success_rate']} | "
                  f"今日进度:{daily['completed']}/{daily['target']}")
        else:
            print(f"[状态] 无活动会话 | 今日进度:{daily['completed']}/{daily['target']}")
    
    def save_session_log(self, filepath: str = None):
        """保存会话日志"""
        if not filepath:
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filepath = f"logs/session_{timestamp}.json"
        
        try:
            log_data = {
                'session_stats': self.session_stats,
                'history_stats': self.history_stats,
                'dashboard_data': self.get_dashboard_data(),
                'export_time': time.time()
            }
            
            Path(filepath).parent.mkdir(parents=True, exist_ok=True)
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(log_data, f, indent=2, ensure_ascii=False)
            
            logger.info(f"[MONITOR] 会话日志已保存: {filepath}")
            
        except Exception as e:
            logger.error(f"[MONITOR] 保存会话日志失败: {e}")
    
    def reset_daily_stats(self):
        """重置每日统计（每日0点调用）"""
        logger.info("[MONITOR] 重置每日统计数据")
        
        self.history_stats.update({
            'daily_total': 0,
            'sessions_today': 0,
            'best_session': 0,
            'avg_session': 0
        })
    
    def get_performance_summary(self) -> Dict:
        """获取性能摘要"""
        return {
            'daily_total': self.history_stats['daily_total'],
            'sessions_count': self.history_stats['sessions_today'],
            'avg_per_session': self.history_stats['avg_session'],
            'best_session': self.history_stats['best_session'],
            'current_success_rate': self.session_stats['success_rate'],
            'total_errors_today': sum(1 for e in self.session_stats['errors'] 
                                    if time.time() - e['timestamp'] < 86400)
        }
